#pragma once
#include <osg/StateSet>
#include <osg/Depth>
#include <osg/CullFace>
#include <osg/BlendFunc>
#include <osg/BlendEquation>

using PrimitiveType = osg::PrimitiveSet::Mode;

/**
 *@note The rendering state set through `setAttributeAndModes` will recursively affect all child nodes by default, 
 *      unless inheritance is explicitly disabled or child nodes override that state.
 */
class StateSet {
public:
    static void setDepthTestAndWrite(osg::Node* node, bool enableDepthTest, bool enableDepthWrite, osg::Depth::Function depthFunc = osg::Depth::LESS) {
        node->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(depthFunc, 0.0, 1.0, enableDepthWrite), enableDepthTest);
    }

    static void setCullingFace(osg::Node* node, bool enable, osg::CullFace::Mode mode = osg::CullFace::BACK) {
        node->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(mode), enable ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
    }

    static void enableBlending(osg::Node* node, GLenum sourceRgba = GL_SRC_ALPHA, GLenum destRgba = GL_ONE_MINUS_SRC_ALPHA, osg::BlendEquation::Equation mode = osg::BlendEquation::FUNC_ADD) {
        auto state = node->getOrCreateStateSet();
        state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
        //ss->setMode(GL_BLEND, osg::StateAttribute::ON);// no need, when apply() GL_BLEND implicitly enabled
        state->setAttributeAndModes(new osg::BlendFunc(sourceRgba, destRgba));
        state->setAttributeAndModes(new osg::BlendEquation(mode));
    }
};